home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************
- * serial.c: Low-level serial device functions.
- * A part of OberSuite for the Commodore Amiga.
- *
- * Author: Daniel Barrett, barrett@cs.umass.edu.
- * Version: 1.0.
- * Copyright: None! This program is in the Public Domain.
- * Please share it with others.
- ***************************************************************************/
-
- #include "decl.h"
- #include "midi.h"
- #include "oberheim.h"
-
- /***************************************************************************
- * A "placeholder" value indicating that a field needs to be filled in later.
- ***************************************************************************/
-
- #define FILL_IN_LATER 0
-
- /***************************************************************************
- * "Global" variables for the serial port structure.
- ***************************************************************************/
-
- static struct MsgPort *MidiPort = NULL;
- static struct IOExtSer *Midi = NULL;
- static long serialFlags = 0L;
-
- /***************************************************************************
- * Flags that indicate which structures have been allocated.
- ***************************************************************************/
-
- #define F_MIDIPORT 1
- #define F_MIDI 2
- #define F_DEVICE 4
- #define F_SERPARAMS 8
-
- /****************************************************************************
- * Prototypes.
- ****************************************************************************/
-
- BOOL MakeSerialDeviceName(char *str, char *device, int *unit);
-
-
- /****************************************************************************
- * SerialSetup: Open the serial port and its message port.
- * By default, we use the device DEFAULT_MIDI_DEVICE, unit DEFAULT_MIDI_UNIT.
- * However, the user may set an environment variable ENVIRONMENT_VAR to
- * indicate the presence of an alternate MIDI device.
- ****************************************************************************/
-
- BOOL SerialSetup(void)
- {
- char deviceName[BUFSIZ], *envVar;
- int unit;
-
- /* Assume we are using the default MIDI device. */
-
- strcpy(deviceName, DEFAULT_MIDI_DEVICE);
- unit = DEFAULT_MIDI_UNIT;
-
- /*
- * If the user has set the environment variable, use that MIDI device
- * instead. If the environment variable value is illegal, quit.
- */
-
- if ((envVar = GetEnv(ENVIRONMENT_VAR))
- && (!MakeSerialDeviceName(envVar, deviceName, &unit)))
- return(FALSE);
-
- /* Do the magic incantations to open the serial device. */
-
- if (! (MidiPort = CreatePort(0, 0)) )
- {
- ErrorMsg(ERROR_CREATEPORT);
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_MIDIPORT;
-
- if (! (Midi = (struct IOExtSer *)
- CreateExtIO(MidiPort, sizeof(struct IOExtSer))))
- {
- ErrorMsg(ERROR_IOEXTSER);
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_MIDI;
-
- Midi->io_SerFlags = SERF_SHARED;
- if (OpenDevice(deviceName, unit, (struct IORequest *)Midi, 0))
- {
- ErrorMsg(ERROR_OPENDEVICE);
-
- if (envVar && ERR_OUTPUT_ALLOWED)
- {
- fprintf(stderr,
- "Perhaps you have the value of your "
- ENVIRONMENT_VAR
- " variable set incorrectly;\n"
- " its value is currently set to \"%s\"\n"
- " (meaning \"DEVICE=%s, UNIT=%d\".)\n",
- envVar, deviceName, unit);
- }
-
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_DEVICE;
-
- Midi->io_SerFlags = SERF_RAD_BOOGIE | SERF_EOFMODE;
- Midi->io_Baud = MIDI_BAUD_RATE;
- Midi->io_TermArray.TermArray0 = 0xF7F7F7F7;
- Midi->io_TermArray.TermArray1 = 0xF7F7F7F7;
- Midi->io_ExtFlags = 0; /* For future compatibility */
- Midi->IOSer.io_Command = SDCMD_SETPARAMS;
- if (DoIO((struct IORequest *)Midi) != 0)
- {
- ErrorMsg(ERROR_SETPARAMS);
- SerialShutdown();
- return(FALSE);
- }
- else
- serialFlags |= F_SERPARAMS;
-
- return(TRUE);
- }
-
-
- /****************************************************************************
- * SerialShutdown: Close the serial port and its message port.
- * Be sure to close things in the opposite order in which they were opened.
- ****************************************************************************/
-
- void SerialShutdown(void)
- {
- if (serialFlags & F_DEVICE)
- {
- ResetSerialPort();
- AbortIO((struct IORequest *)Midi);
- WaitIO((struct IORequest *)Midi);
- CloseDevice((struct IORequest *)Midi);
- }
-
- if (serialFlags & F_MIDI)
- DeleteExtIO((struct IORequest *)Midi);
-
- if (serialFlags & F_MIDIPORT)
- DeletePort(MidiPort);
- }
-
- /****************************************************************************
- * ResetSerialPort: Clear all data from the serial port.
- ***************************************************************************/
-
- void ResetSerialPort(void)
- {
- Midi->IOSer.io_Command = CMD_CLEAR;
- DoIO((struct IORequest *)Midi);
- }
-
-
- /****************************************************************************
- * Is any data there?
- ***************************************************************************/
-
- long AnyMidiData(void)
- {
- Midi->IOSer.io_Command = SDCMD_QUERY;
- DoIO((struct IORequest *)Midi);
- return(Midi->IOSer.io_Actual);
- }
-
-
- /****************************************************************************
- * PrepareToReadMidi: Prepare a READ request for the MIDI port.
- * PrepareToWriteMidi: Prepare a WRITE request for the MIDI port.
- ***************************************************************************/
-
- void PrepareToReadMidi(UBYTE buf[], int len)
- {
- Midi->IOSer.io_Command = CMD_READ;
- Midi->IOSer.io_Data = (APTR)buf;
- Midi->IOSer.io_Length = len;
- }
-
-
- void PrepareToWriteMidi(UBYTE buf[], int len)
- {
- Midi->IOSer.io_Command = CMD_WRITE;
- Midi->IOSer.io_Data = (APTR)buf;
- Midi->IOSer.io_Length = len;
- }
-
-
- /****************************************************************************
- * DoTheIO: General-purpose MIDI I/O routine. Quits on ^C.
- ****************************************************************************/
-
- long DoTheIO(void)
- {
- int mask, temp;
- long bytesDone = 0L;
-
- mask = SIGBREAKF_CTRL_C | (1L << MidiPort->mp_SigBit);
- SendIO((struct IORequest *)Midi);
-
- while (1)
- {
- temp = Wait(mask);
- if (temp & SIGBREAKF_CTRL_C)
- {
- bytesDone = CTRL_C_NO_BYTES;
- break;
- }
-
- if (CheckIO((struct IORequest *)Midi))
- {
- WaitIO((struct IORequest *)Midi);
- bytesDone = Midi->IOSer.io_Actual;
- break;
- }
- }
-
- AbortIO((struct IORequest *)Midi);
- WaitIO((struct IORequest *)Midi);
- return(bytesDone);
- }
-
-
- /****************************************************************************
- * RequestOnePatch: Request a patch dump from an Oberheim synth.
- ***************************************************************************/
-
- void RequestOnePatch(UBYTE patchNum, int mode)
- {
- static UBYTE request[7] = { SYSEX_BEGIN,
- OBERHEIM_SYSEX_ID,
- OBERHEIM_DEVICE_NUMBER,
- DUMP_REQUEST,
- FILL_IN_LATER,
- FILL_IN_LATER,
- SYSEX_END };
-
- request[BYTE_PATCHTYPE] = (UBYTE)mode;
- request[BYTE_PATCHNUMBER] = patchNum;
-
- ResetSerialPort();
- Midi->IOSer.io_Command = CMD_WRITE;
- Midi->IOSer.io_Data = (APTR)request;
- Midi->IOSer.io_Length = sizeof(request);
- (void)DoTheIO();
- }
-
-
- /***************************************************************************
- * Environment variable functions.
- ***************************************************************************/
-
- /*
- * Given the string "str", break it into the device name and unit number.
- * Environment variable syntax is "DEVICENAME:UNITNUMBER".
- * For example: "midi.device:2".
- *
- * "device" MUST preallocated.
- */
-
- BOOL MakeSerialDeviceName(char *str, char *device, int *unit)
- {
- /*
- * Copy "str" into the device name, until we reach a ':' or run out
- * of data.
- */
-
- while (str && *str && (*str != ':'))
- *(device++) = *(str++);
-
- /* Terminate the device name, so it is a valid string. */
-
- *device = '\0';
-
- /* If we did not reach a colon, complain and exit! */
-
- if ((*str != ':') || *(str+1) == '\0')
- {
- ErrorMsg(ERROR_OBDEVICE);
- return(FALSE);
- }
-
- /* Skip the colon. */
-
- str++;
-
- /*
- * The remaining string data must represent a non-negative integer.
- * If so, grab the data as the value of "unit".
- * Otherwise, complain and exit!
- */
- if (!AllDigits(str))
- {
- ErrorMsg(ERROR_OBUNIT);
- return(FALSE);
- }
- else
- *unit = atoi(str);
-
- /* If we got here, everything is just groovy! */
-
- return(TRUE);
- }
-